home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1997 May / EnigmA AMIGA RUN 18 (1997)(G.R. Edizioni)(IT)[!][issue 1997-05][EAR-CD II].iso / softwareupdate / system / amigados / advancedroutines / example4.c < prev    next >
C/C++ Source or Header  |  1996-10-10  |  11KB  |  384 lines

  1. /***********************************************************/
  2. /*                                                         */
  3. /* Amiga C Encyclopedia (ACE)           Amiga C Club (ACC) */
  4. /* --------------------------           ------------------ */
  5. /*                                                         */
  6. /* Manual:  AmigaDOS                    Amiga C Club       */
  7. /* Chapter: Advanced Routines           Tulevagen 22       */
  8. /* File:    Example4.c                  181 41  LIDINGO    */
  9. /* Author:  Anders Bjerin               SWEDEN             */
  10. /* Date:    93-03-17                                       */
  11. /* Version: 1.1                                            */
  12. /*                                                         */
  13. /*   Copyright 1993, Anders Bjerin - Amiga C Club (ACC)    */
  14. /*                                                         */
  15. /* Registered members may use this program freely in their */
  16. /*     own commercial/noncommercial programs/articles.     */
  17. /*                                                         */
  18. /***********************************************************/
  19.  
  20. /* This program will examina all objects in a directory/device.   */
  21. /* The files will be listed, and if finds a directory it will     */
  22. /* with help of a recursive function examine all objects in       */
  23. /* that directory also and so on... Good example on how to use    */
  24. /* the Examine() and ExNext() functions in a recursive program.   */
  25. /*                                                                */
  26. /* This example can be used with all versions of the dos library. */
  27.  
  28.  
  29.  
  30. /* Please note that this example is  */
  31. /* for experienced programmers only! */
  32.  
  33.  
  34.  
  35. /* Include the dos library definitions: */
  36. #include <dos/dos.h>
  37.  
  38. /* Include memory definitions: */
  39. #include <exec/memory.h>
  40.  
  41. /* Now we include the necessary function prototype files:         */
  42. #include <clib/dos_protos.h>       /* General dos functions...    */
  43. #include <clib/exec_protos.h>      /* System functions...         */
  44. #include <stdio.h>                 /* Std functions [printf()...] */
  45. #include <stdlib.h>                /* Std functions [exit()...]   */
  46. #include <string.h>                /* Std functions [strcpy()...] */
  47.  
  48.  
  49.  
  50. /* The maximum numbers of characters that can be */
  51. /* stored in the complete file name with path:   */
  52. #define MAX_LENGTH 120
  53.  
  54. /* The number of characters we will indent the line */
  55. /* when we go inside another directory:             */
  56. #define INDENT_LENGTH 4
  57.  
  58. /* The highest accceptable indent value: */
  59. #define MAX_INDENT  80
  60.  
  61.  
  62.  
  63. /* Set name and version number: */
  64. UBYTE *version = "$VER: AmigaDOS/Advanced Routines/Example4 1.1";
  65.  
  66.  
  67.  
  68. /* Declared our own functions: */
  69.  
  70. /* Our main function: */
  71. int main( int argc, char *argv[] );
  72.  
  73. /* Our recursive directory lister: */
  74. int ExamineDirectory( STRPTR dir_name, int indent );
  75.  
  76. /* Adds a directory name to a path: */
  77. void AddToPath
  78. (
  79.   STRPTR complete,
  80.   STRPTR name,
  81.   STRPTR path 
  82. );
  83.  
  84.  
  85.  
  86. /* Main function: */
  87.  
  88. int main( int argc, char *argv[] )
  89. {
  90.   /* Store result code here: */
  91.   int problems;
  92.  
  93.   
  94.  
  95.   /* The program name and one argument must have been entered: */
  96.   if( argc < 2  || argc > 2)
  97.   {
  98.     /* Wrong number of arguments! */
  99.     printf( "Error! Wrong number of arguments!\n" );
  100.     printf( "You must enter a directory or volume name.\n" );
  101.     printf( "Example4 Name/A\n" ); /* Simple template */
  102.  
  103.     /* Exit with an error code: */
  104.     exit( 20 );
  105.   }
  106.  
  107.  
  108.  
  109.   /* Examine the directory: */
  110.   problems = ExamineDirectory( argv[ 1 ], 0 );
  111.  
  112.   /* Any problems? */
  113.   if( problems )
  114.     printf( "There were problems, error code: %d\n", problems );
  115.  
  116.  
  117.  
  118.   /* The End! */
  119.   exit( problems );
  120. }
  121.  
  122.  
  123.  
  124. /* This function will:                                           */
  125. /*   1. allocate some momory for a file info block structure.    */
  126. /*   2. lock the directory.                                      */
  127. /*   3. Examine the directory, and check that it is a directory. */
  128. /*   4. List all objects in this directory and return when done. */
  129. /*   5. If there are any directory inside this directory we call */
  130. /*      ourself, and we have a nice recursive function...        */
  131.  
  132. int ExamineDirectory( STRPTR dir_name, int indent )
  133. {
  134.   /* This string will be used to store the complete name and path in: */
  135.   UBYTE total_name[ MAX_LENGTH ];
  136.  
  137.   /* Our indent string: */
  138.   UBYTE indent_string[ MAX_INDENT ];
  139.  
  140.   /* Simple loop variable: */
  141.   int loop;
  142.   
  143.   /* String pointer: */
  144.   STRPTR str_ptr;
  145.  
  146.   /* Store result codes here: */
  147.   int result_code;
  148.   
  149.   /* A BCPL pointer to a file lock: */
  150.   BPTR my_lock;
  151.  
  152.   /* Declare a pointer to a FileInfoStructure: (This structure  */
  153.   /* must be long word aligned - start on an even word address. */
  154.   /* To do this we must therefore allocate the structure with   */
  155.   /* help of AllocMem(). If you have the new dos 2.xx or higher */
  156.   /* you are recommended to use the AllocDosObject() function.  */
  157.   /* This will be explained in the next version of the ACE.)    */
  158.   struct FileInfoBlock *my_file_info_block;
  159.  
  160.  
  161.  
  162.   /* Set the result code to OK: */
  163.   result_code = 0;
  164.  
  165.   /* Allocate enough memory for a FileInfoBlock structure: */
  166.   /* (Any type of memory, fast or chip, and clear it.)     */
  167.   my_file_info_block = (struct FileInfoBlock *)
  168.     AllocMem( sizeof( struct FileInfoBlock ), MEMF_ANY | MEMF_CLEAR );
  169.  
  170.   /* Check if we have allocated the memory successfully: */
  171.   if( my_file_info_block == NULL )
  172.   {
  173.     /* Inform the user about the problem: */
  174.     printf( "Not enough memory!\n" );
  175.  
  176.     /* Return with an error code: */
  177.     return( 21 );
  178.   };
  179.  
  180.  
  181.   
  182.   /* We will now try to lock the directory: (We will */
  183.   /* only read data so we can use a shared lock.)    */
  184.   my_lock = Lock( dir_name, ACCESS_READ );
  185.   
  186.   /* Colud we lock the file? */
  187.   if( my_lock == NULL )
  188.   {
  189.     /* Inform the user about the problem: */
  190.     printf( "Could not lock the directory \"%s\"\n", dir_name );
  191.  
  192.     /* Deallocate the memory we have allocated: */
  193.     FreeMem( my_file_info_block, sizeof( struct FileInfoBlock ) );
  194.     
  195.     /* Return with an error code: */
  196.     return( 22 );
  197.   }
  198.  
  199.  
  200.  
  201.   /* Prepare the indent string: */
  202.  
  203.   /* If we have not indented the line too much we indent it: */
  204.   if( indent < MAX_INDENT )
  205.   {  
  206.     /* Fill the indent string with spaces: */
  207.     for( loop = 0; loop < MAX_INDENT; loop++ )
  208.       indent_string[ loop ] = ' ';
  209.   
  210.     /* Set the stop (NULL) sign: (The higher the indent value is */
  211.     /* the further in the string we set the NULL sign.)          */
  212.     str_ptr = indent_string + indent;
  213.  
  214.     /* Set the NULL sign: */
  215.     *str_ptr = NULL;
  216.   }
  217.  
  218.  
  219.  
  220.   /* Try to examine the directory: */
  221.   if( Examine( my_lock, my_file_info_block ) )
  222.   {
  223.     /* Check if it is really a directory: */
  224.     if( my_file_info_block->fib_DirEntryType > 0 )
  225.     {
  226.       /* Yes, this is a directory! */
  227.       
  228.       /* Examine all objects in this directory: */
  229.  
  230.       /* As long as we find objects in this directory we continue: */
  231.       while( ExNext( my_lock, my_file_info_block ) )
  232.       {
  233.         /* If we find a file we print out the name, and if we */
  234.         /* find a directory we cal our self (recursive):      */
  235.         if( my_file_info_block->fib_DirEntryType < 0 )
  236.         {
  237.           /* It is a file! */
  238.             
  239.           /* Print the file name: */
  240.           printf( "%s%s\n",
  241.             indent_string, my_file_info_block->fib_FileName );
  242.         }
  243.         else
  244.         {
  245.           /* It is a directory, and should therefore call our self! */
  246.  
  247.           /* Print the directory name: */
  248.           printf( "%s%s (Directory)\n",
  249.             indent_string, my_file_info_block->fib_FileName );
  250.  
  251.           /* However, first we must add the directory name to the */
  252.           /* current path (the "fib_FileName" field only contains */
  253.           /* the file name of the directory, not the path):       */
  254.  
  255.           AddToPath( total_name,                       /* Name & Path */
  256.                      my_file_info_block->fib_FileName, /* Name        */
  257.                      dir_name                          /* Path        */
  258.                    );
  259.  
  260.           result_code =
  261.             ExamineDirectory( total_name, indent + INDENT_LENGTH );
  262.         }
  263.       }
  264.  
  265.  
  266.  
  267.       /* We have now left the while loop. It was either because there  */
  268.       /* were no more objects in the directory, or there was an error: */
  269.       /* (If the error message isn't "ERRROR_NO_MORE_ENTRIES" it was   */
  270.       /* an error.)                                                    */
  271.       if( IoErr() != ERROR_NO_MORE_ENTRIES )
  272.       {
  273.         /* Inform the user: */
  274.         printf( "Error while reading directory \"%s\"!\n", dir_name );
  275.  
  276.         /* Set an error code: */
  277.         result_code = 23;
  278.       }
  279.     }
  280.     else
  281.     {
  282.       /* (This can only happen the first time this function */
  283.       /* is called, since we will only call ourself if we   */
  284.       /* know it is a directory.)                           */
  285.  
  286.       /* The user tried to examine a file! */
  287.       printf( "\"%s\" is a file!\n", dir_name );
  288.  
  289.       /* No directory specified! */
  290.       printf( "You must enter directory name!\n" );
  291.  
  292.       /* Give the user a command line template: */
  293.       printf( "RecursiveExamine DIRECTORY/A\n" );
  294.  
  295.       /* Set an error code: */
  296.       result_code = 24;
  297.     }
  298.   }
  299.   else
  300.   {
  301.     /* We could no examine the object: */
  302.     printf( "Could not examine %s!\n", dir_name );
  303.  
  304.     /* Set an error code: */
  305.     result_code = 25;
  306.   }
  307.  
  308.  
  309.  
  310.   /* Unlock the file: */
  311.   UnLock( my_lock );  
  312.  
  313.   /* Deallocate the memory we have allocated: */
  314.   FreeMem( my_file_info_block, sizeof( struct FileInfoBlock ) );
  315.  
  316.   return( result_code );
  317. }
  318.  
  319.  
  320.  
  321. /* This function will copy the path to the complete string, and */
  322. /* then add the directory name together with a "/" sign if      */
  323. /* necessary.                                                   */
  324.  
  325. void AddToPath
  326. (
  327.   STRPTR complete,
  328.   STRPTR name,
  329.   STRPTR path 
  330. )
  331. {
  332.   /* A temporary string pointer: */
  333.   STRPTR string_pointer;
  334.  
  335.  
  336.  
  337.   /* Put a stop character at the beginning of the complete string: */
  338.   complete[ 0 ] = NULL;
  339.  
  340.  
  341.  
  342.   /* Move to the last character in the string: (Isn't C nice?) */
  343.   string_pointer = (STRPTR) path + strlen( path ) - 1;
  344.  
  345.   /* Check what the right most character in the path string is: */
  346.   if
  347.   ( 
  348.     *string_pointer == ':' ||
  349.     *string_pointer == '/' ||
  350.     *string_pointer == '\0'
  351.   )
  352.   {
  353.     /* We can simply add the directory to the path string:   */
  354.     /* (Just check that there is enough room before we add   */
  355.     /* the directory.)                                       */
  356.     if( strlen( path ) + strlen( name ) < MAX_LENGTH )
  357.     {
  358.       /* Copy the path to the complete string: */
  359.       strcpy( complete, path );
  360.  
  361.       /* Add the directory name to the path: */
  362.       strcat( complete, name );
  363.     }
  364.   }
  365.   else
  366.   {
  367.     /* We have to add the '/' sign before we add the directory name: */
  368.     /* (Just check that there is enough room before we add them!)    */
  369.     if( strlen( path ) + 1 + strlen( name ) < MAX_LENGTH )
  370.     {
  371.       /* Copy the path to the complete string: */
  372.       strcpy( complete, path );
  373.  
  374.       /* Add the "/" sign: */
  375.       strcat( complete, "/" );
  376.  
  377.       /* Add the directory name to the path: */
  378.       strcat( complete, name );
  379.     }
  380.   }
  381. }
  382.  
  383.  
  384.